package com.project1.cmpe473;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RMISecurityManager;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.ArrayList;
import java.util.LinkedList;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class HeadHunter extends HttpServlet {
	private static final long serialVersionUID = 1L;
    public HeadHunter() {

    }

	protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		
		
		RequestDispatcher dispatcher =   getServletContext().getRequestDispatcher("/user.jsp");
		dispatcher.forward(request, response);
	}

	protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String error="";
		try{
			//gets the name-surname field and checks required name-surname field filled
			String nameSurname=request.getParameter("name-surname");
			if(nameSurname.equals(""))
				error="Name cannot be empty";
			
			//gets the university field and checks required university field filled
			String university=request.getParameter("university");
			if(university.equals(""))
				error="University cannot be empty";
			
			//gets the gpa field and checks required gpa field filled
			String gpaString=request.getParameter("gpa");
			double gpa=0;
			if(!gpaString.equals(""))
			{
				//looks gpa is in required format
				if (!gpaString.matches("^[1-9]\\d*(.\\d+)?$") && !gpaString.matches("^[1-9]\\d*(,\\d+)?$")) {
				    error="Invalid gpa";
				}
				else
				{
					gpaString=gpaString.replace(',', '.');
					gpa=Double.parseDouble(gpaString);
				}
			}
			else
				error="Gpa cannot be empty";
				
	
			//gets the degree field and checks required degree field filled
			String[] degreeArray = request.getParameterValues("degree");
			ArrayList<Integer> degreeList= new ArrayList<Integer>();
			if (degreeArray != null && degreeArray.length != 0)
			{
				for(String degree : degreeArray)
				{
					degreeList.add(Integer.parseInt(degree));
				}
			}
			else
				error="Invalid degree";
			
			
			//gets the experience field and checks required experience field valid
			String expString=request.getParameter("experience");
			int experience=0;
			if(!expString.equals(""))
			{
				if (!expString.matches("^\\d+$")) {
				    error="Invalid experience";
				}
				else
					experience= Integer.parseInt(expString);
			}
			
			//gets the gender field and checks gender field filled
			String[] genderArray = request.getParameterValues("gender");
			ArrayList<String> genderList= new ArrayList<String>();
			if (genderArray != null && genderArray.length != 0)
			{
				for(String gender : genderArray)
				{
					genderList.add(gender);
				}
			}
			else
				error="Invalid gender";
			
			//puts the error the screen
			if(error!="")
			{
				request.setAttribute("error",error);
				RequestDispatcher dispatcher =   getServletContext().getRequestDispatcher("/user.jsp");
				dispatcher.forward(request, response);
			}
			else
			{		
				Applicant applicant=new Applicant(nameSurname, university, gpa ,degreeList.get(0), experience, genderList.get(0));
				
				LinkedList<Company> suitableCompanies= findCompanies(applicant);
				ArrayList<Company> approvedCompanies=new ArrayList<Company>();
				try {
					
					//RMI PART
					//for each suitable company, get approval
					for(Company company : suitableCompanies)
					{
						boolean approvalResponse=false;
						Registry reg = LocateRegistry.getRegistry("localhost");
						Approval approval=(Approval) reg.lookup("Company"+company.id);
			
						approvalResponse= approval.getApproval(applicant);
						
						if(approvalResponse)
							approvedCompanies.add(company);
					}
				} catch (NotBoundException e) {
					e.printStackTrace();
				}
				
				
				//puts the result to the user
				String result="";
				for(Company company : approvedCompanies)
				{
					result+=company.name + ", ";
				}
				if(approvedCompanies.size()==0)
					result="No companies ";
				
				request.setAttribute("response",result);
				RequestDispatcher dispatcher =   getServletContext().getRequestDispatcher("/user.jsp");
				dispatcher.forward(request, response);
			}
		}
		catch (Exception e) {
			error="An error occured: "+e.getMessage();
			request.setAttribute("error",error);
			RequestDispatcher dispatcher =   getServletContext().getRequestDispatcher("/user.jsp");
			dispatcher.forward(request, response);
		}
	}
	
	//finds any suitable company based on the information provided by the companies

	public LinkedList<Company> findCompanies(Applicant applicant) throws IOException{
		LinkedList<Company> companies = new LinkedList<Company>();
		
		for(Company company: CompanyForm.companyList)
		{
			if(isMatch(company, applicant))
				companies.add(company);
		}
		
		return companies;
	}
	
	//the real stuff part to find any suitable company
	public boolean isMatch(Company company, Applicant applicant)
	{
		if(company==null || applicant == null)
			return false;
		
		if(company.univeristy!="" && company.univeristy!=null)
		{
			if(applicant.univeristy!="" && applicant.univeristy!=null)
			{
				if(!applicant.univeristy.equalsIgnoreCase(company.univeristy))
				{
					return false;
				}
			}
			else
				return false;
		}
		if(applicant.gpa<company.gpa)
		{
			return false;			
		}
		if(applicant.degree<company.degree)
		{
			return false;
		}
		if(applicant.experience<company.experience)
		{
			return false;
		}
		if(company.genders.size()!=0)
		{
			if(!company.genders.contains(applicant.gender))
			{
				return false;
			}
		}
		return true;
	}
}
